import Vue from 'vue'
import Vuex from 'vuex'
import http from '../src/utils/http'

Vue.use(Vuex)


// 很久前整理过 localStorage 和 sessionStorage 的区别的联系，今天再来整理一下他们和 Vuex 中的 $store.state 的区别。

// 1、存储位置及类型：
// localStorage 和 sessionStorage 是存在本地缓存；
// Vuex 是存储在内存中。
// localStorage 和 sessionStorage 只能存储字符串类型，对于复杂的对象可以使用 
// ECMAScript 提供的 JSON 对象的 stringify 和 parse 来处理。


// 2、实效性：
// localStorage（本地存储）存储在本地，永久保存；
// sessionStorage（会话存储），临时保存，页面关闭即失效；
// Vuex 页面刷新时会失效，因为 Vuex 是存在内存中，当页面（F5）刷新时属于清除内存，Vuex 存储的值会丢失。


// 3、应用场景：
// Vuex 用于组件之间的传值；
// localStorage ，sessionStorage 则主要用于不同页面之间的传值。


// 其他：
// 很多同学觉得用 localstorage 可以代替 Vuex，对于不变的数据确实可以，
// 但是当两个组件共用一个数据源（对象或数组）时，如果其中一个组件改变了该数据源，希望另一个组件响应该变化时，
// localstorage，sessionstorage 是无法做到，原因就是区别1。

const store = new Vuex.Store({
  state: {
    message: {},
    weathermsg: {},
    userMenus: [],
    userRoutes: [],
  },
  mutations: {
    // 通俗理解mutations，里面装着一些改变数据方法的集合，
    // 这是Vuex设计很重要的一点，就是把处理数据逻辑方法全部放在mutations里面，
    // 使得数据和视图分离
    //注册事件，type:increment，handler第一个参数是state；
    // 每一个mutation都有一个字符串类型的事件类型(type)和回调函数(handler)
    // ，也可以理解为{type:handler()} ，这和订阅发布有点类似。
    // 先注册事件，当触发响应类型的时候调用handker()，
    // 调用type的时候需要用到store.commit方法。
    //  this.$store.commit("increment", item);  //调用type，触发handler（state payload）   
    replacewarn(state, message) {
      state.message = message
    },
    saveweather(state, message) {
      state.weathermsg = message
    },
    saveroute(state, message) {
      state.userroute = message
    },
    saveuserRoutes( state, value ){
      state.userRoutes=value;
    },
    saveuserMenus(state, value){
      state.userMenus=value;
    },
  },
  actions: {
    loginout() {
      this.$http.post('/user/logout', params).then(res => {
        if (res.data.h.code == 0) {
          sessionStorage.removeItem('LoginUser')
          location.reload()//重新导入当前页面
        }
      })
        .catch(err => {
          console.error(err);
        });
    },





//context的话就相当于state的父亲，上一级，包含着state中的所有属性
// context:{undefined
//         state,   等同于store.$state，若在模块中则为局部状态
//         rootState,   等同于store.$state,只存在模块中
//         commit,   等同于store.$commit
//         dispatch,   等同于store.$dispatch
//         getters   等同于store.$getters
// }

// 常规写法调用的时候会使用context.commit，但更多的是使用es6的变量解构赋值，也就是直接在参数的
// 位置写自己想要的属性，如：{commit}。
 
// 例如：
// prev ({dispatch, state}) {undefined
//       const list = state.listInfo.songList
//       if (state.listInfo.songIndex === 0) {undefined
//         state.listInfo.songIndex = list.length
//       } else {undefined
//         state.listInfo.songIndex--
//       }
//       const hash = list[state.listInfo.songIndex] && list[state.listInfo.songIndex].hash
//       dispatch('getSong', hash)
//     },

// dispatch：含有异步操作；而commit只是同步操作，都是提交 mutation，
//因为只能在mutation中才能够改变state中的值，然而mutation中只能进行同步操作，
//从而actions就出现了，actions允许异步和同步操作，但是对于actions的操作其实就是提交mutation来完成；
    saveAction: (context, message) => {
      context.commit("saveweather", message)
    },


    //dispatch   ActionS  commit  mutations
    async getMenu( {commit} ) {
      //请求当前用户所拥有的权限
      let res = await http.get('/router/list')
      if (res.data.h.code == 0) {
        let oneArr = [],
        anotherArr = [];

        oneArr = res.data.b.filter((item) => !item.parentId); //一级路由
        anotherArr = res.data.b.filter((item) => item.parentId); //二级路由  z子级别路由


        // // What you have
        // var officers = [
        //     { id: 20, name: 'Captain Piett' },
        //     { id: 24, name: 'General Veers' },
        //     { id: 56, name: 'Admiral Ozzel' },
        //     { id: 88, name: 'Commander Jerjerrod' }
        // ];
        // // What you need
        // [20, 24, 56, 88]

        // .map() .filter() .reduce() 的用法
        // var officersIds = [];
        // officers.forEach(function (officer) {
        // officersIds.push(officer.id);
        // });

        // var rebels = pilots.filter(function (pilot) {
        //     return pilot.faction === "Rebels";
        //   });
        //  总结：如果 callback 函数返回 true，这个元素将会出现在返回的数组中，如果返回 false 就不会出现在返回数组中

        // const officersIds = officers.map(officer => officer.id);
        // 那么 .map() 是怎么运行的呢？实际上对数组的每个元素都遍历一次，
        // 同时返回一个新的值。记住一点是返回的这个数据的长度和原始数组长度是一致的


        // 如果你需要知道所有飞行员的总飞行年数。用 .reduce() 将会非常直观。
        // var totalYears = pilots.reduce(function (accumulator, pilot) {
        //     return accumulator + pilot.years;
        //   }, 0);

        // 可以看到我们开始先用0初始化了我们的 accumulator 的值，
        // 如果需要我们可以用其他的值去初始化 accumulator 。 在对每个元素运行 callback 函数之后，
        // reduce 将会返回最终值给我们（例子中：82）
        // 同样我们可以用箭头函数精简我们的代码
        // const totalYears = pilots.reduce((acc, pilot) => acc + pilot.years, 0);


        // .map() .filter() .reduce() 结合使用
        // 因为 .map() 和 .filter()都返回一个数组，所以我们可以轻松的用链式编程的方法来综合使用它们。
        // 我们的目标是：获取属性为 force 的用户总值
        // var totalJediScore = personnel
        // .filter(function (person) {
        //     return person.isForceUser;
        // })
        // .map(function (jedi) {
        //     return jedi.pilotingScore + jedi.shootingScore;
        // })
        // .reduce(function (acc, score) {
        //     return acc + score;
        // }, 0);


        // const totalJediScore = personnel
        // .filter(person => person.isForceUser)
        // .map(jedi => jedi.pilotingScore + jedi.shootingScore)
        // .reduce((acc, score) => acc + score, 0);



        oneArr.map((obj) => {
          obj.children = [];
        });

        anotherArr.map((item) => {
          oneArr.map((obj) => {
            if (item.parentId == obj.id) {
              obj.children.push(item);
            }
          });
        });
        
        commit('saveuserRoutes', anotherArr )
        commit('saveuserMenus',  oneArr )

        return {code: 0, data: res.data}
      }
    },

  }
})
export default store